import { ref } from 'vue'
import { ComponentType, CustomFormFieldVal, OrderDataListItem } from './types'
import { v4 as uuidv4 } from 'uuid'
import { useFindTemplateById } from './useTemplateList'

const { template, findTemplate } = useFindTemplateById()

const orderList = ref<Array<OrderDataListItem>>([])

const saveOrderListToBrowserLocal = () => {
  sessionStorage.setItem('orderCustomDataManager', JSON.stringify(orderList.value))
}

const sleep = (timestamp: number) => {
  return new Promise((resolve) => setTimeout(resolve, timestamp))
}

export const useSetOrderListFromBrowserLocal = () => {
  try {
    const _orderList = sessionStorage.getItem('orderCustomDataManager')
    if (_orderList) {
      orderList.value = JSON.parse(_orderList)
    }
  } catch (error) {
    // error
  }
}

export const useOrderSave = () => {
  const form = ref<Record<string, CustomFormFieldVal>>({})
  const formSaveLoading = ref(false)

  const formSave = async (templateId: string) => {
    formSaveLoading.value = true
    await findTemplate(templateId)
    formSaveLoading.value = false
    orderList.value.push({
      id: uuidv4(),
      templateId,
      form: form.value,
      flow: {
        id: template.value.processList[0].id,
        nodes: template.value.processList[0].nodes,
      },
      currentNodeId: template.value.processList[0].nodes[1].id,
      flowHistory: [
        {
          nodeId: template.value.processList[0].nodes[0].id,
          duration: 1,
          startTime: new Date().getTime(),
        },
      ],
    })
    saveOrderListToBrowserLocal()
  }

  const resetForm = () => {
    form.value = {}
  }

  return {
    form,
    formSaveLoading,
    formSave,
    resetForm,
  }
}

export const useCopyOrder = () => {
  const copyLoading = ref(false)

  const copy = async (order: OrderDataListItem) => {
    copyLoading.value = true
    await sleep(2000)
    copyLoading.value = false
    order.id = uuidv4()
    orderList.value.push(order)
  }

  return {
    copyLoading,
    copy,
  }
}

export const useOrderUpdate = () => {
  const updateLoading = ref(false)
  const orderForm = ref<OrderDataListItem>({
    id: '',
    templateId: '',
    form: {},
    flow: {
      id: '',
      nodes: [],
    },
    currentNodeId: '',
    flowHistory: [],
  })

  const update = (startTime: number) => {
    const orderIndex = orderList.value.findIndex((item) => item.id === orderForm.value.id)
    if (orderIndex === -1) {
      return
    }
    const nodeIndex = orderForm.value.flow.nodes.findIndex(
      (item) => item.id === orderForm.value.currentNodeId,
    )
    if (nodeIndex === -1) {
      return
    }
    const node = orderForm.value.flow.nodes[nodeIndex]
    if (!node || node.isEnd) {
      return
    }

    const nextNode = orderForm.value.flow.nodes[nodeIndex + 1]
    if (!nextNode) {
      return
    }

    orderForm.value.currentNodeId = nextNode.id
    orderForm.value.flowHistory.unshift({
      nodeId: node.id,
      startTime,
      duration: new Date().getTime() - startTime,
    })

    if (nextNode.isEnd) {
      orderForm.value.flowHistory.unshift({
        nodeId: nextNode.id,
        startTime,
        duration: 0,
      })
    }

    orderList.value[orderIndex] = orderForm.value
    saveOrderListToBrowserLocal()
  }

  return {
    orderForm,
    updateLoading,
    update,
  }
}

export const useOrderEnd = () => {
  const endLoading = ref(false)

  const end = async (orderId: string) => {
    endLoading.value = true
    const orderIndex = orderList.value.findIndex((order) => order.id === orderId)
    if (orderIndex === -1) {
      return
    }

    const order = orderList.value[orderIndex]
    const endNode = order.flow.nodes.find((node) => node.isEnd)
    if (!endNode) {
      return
    }

    order.currentNodeId = endNode.id
    order.flowHistory.unshift({
      nodeId: endNode.id,
      startTime: new Date().getTime(),
      duration: 1,
    })
    orderList.value[orderIndex] = order
    saveOrderListToBrowserLocal()
    await sleep(1000)
    endLoading.value = false
  }

  return {
    endLoading,
    end,
  }
}

export const useOrderDel = () => {
  const delLoading = ref(false)

  const del = (orderId: string) => {
    const orderIndex = orderList.value.findIndex((order) => order.id === orderId)
    if (orderIndex !== -1) {
      orderList.value.splice(orderIndex, 1)
      saveOrderListToBrowserLocal()
    }
  }

  return {
    delLoading,
    del,
  }
}

export const useGetOrderList = () => {
  const getOrderListLoading = ref(false)
  const getOrderListParam = ref({
    name: '',
    limit: 50,
    page: 1,
  })
  const orderListTotal = ref(0)
  const _orderList = ref<
    Array<{
      id: string
      value: Record<
        string,
        {
          value: CustomFormFieldVal | null
          label: string
          type: ComponentType | null
        }
      >
    }>
  >([])

  const getOrderList = async (templateId: string) => {
    _orderList.value.length = 0
    useSetOrderListFromBrowserLocal()
    const dataList = orderList.value.filter((item) => item.templateId === templateId)
    if (!dataList) {
      return
    }

    getOrderListLoading.value = true
    await findTemplate(templateId)

    dataList.forEach((data) => {
      const result: {
        id: string
        value: Record<
          string,
          {
            value: CustomFormFieldVal | null
            label: string
            type: ComponentType | null
          }
        >
      } = {
        id: '',
        value: {},
      }
      for (let i = 0; i < template.value.componentList.length; i++) {
        const component = template.value.componentList[i]
        result.value[component.id] = {
          value: data.form[component.id],
          label: component.label,
          type: component.type,
        }
      }
      result.id = data.id
      _orderList.value.push(result)
    })
    orderListTotal.value = _orderList.value.length
    getOrderListLoading.value = false
  }

  return {
    orderList: _orderList,
    orderListTotal,
    getOrderListParam,
    getOrderListLoading,
    getOrderList,
  }
}

export const useFindOrderById = () => {
  const findOrderLoading = ref(false)
  const order = ref<OrderDataListItem>({
    id: '',
    templateId: '',
    form: {},
    flow: {
      id: '',
      nodes: [],
    },
    currentNodeId: '',
    flowHistory: [],
  })

  const findOrder = async (id: string) => {
    findOrderLoading.value = true
    await sleep(2000)
    findOrderLoading.value = false
    const orderIndex = orderList.value.findIndex((item) => item.id === id)
    if (orderIndex !== -1) {
      order.value = orderList.value[orderIndex]
    }
  }

  return {
    order,
    findOrderLoading,
    findOrder,
  }
}
